package com.wangfugui.mybatisplus.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.wangfugui.mybatisplus.dao.PortfolioInformationDao;
import com.wangfugui.mybatisplus.domain.PortfolioInformation;
import com.wangfugui.mybatisplus.service.PortfolioInformationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.Year;
import java.time.YearMonth;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

import static com.sun.xml.internal.ws.policy.sourcemodel.wspolicy.XmlToken.Optional;


@Service
@Slf4j
public class PortfolioInformationServiceImpl extends ServiceImpl<PortfolioInformationDao, PortfolioInformation> implements PortfolioInformationService {




    @Override
    public PortfolioInformation getYesTodayInformation(Date reportDate) {
        LambdaQueryWrapper<PortfolioInformation> wrapper = new LambdaQueryWrapper<>();
        wrapper.lt(PortfolioInformation::getDate, reportDate).orderByDesc(PortfolioInformation::getDate).last("LIMIT 1");
        return this.getOne(wrapper);
    }
    public List<PortfolioInformation> getLastOfMonthData(List<PortfolioInformation> list) {
        if (list == null || list.isEmpty()) {
            return new ArrayList<>();
        }

        // 按日期排序
        list.sort(Comparator.comparing(PortfolioInformation::getDate));

        Map<YearMonth, PortfolioInformation> resultMap = new LinkedHashMap<>();

        for (PortfolioInformation item : list) {
            Date date = item.getDate();
            YearMonth yearMonth = YearMonth.from(date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate());

            // 由于列表已排序，后面的记录会覆盖前面的记录，最终保留每月最后一条
            resultMap.put(yearMonth, item);
        }

        return new ArrayList<>(resultMap.values());
    }

    @Override
    public String getITDPnl(Date reportDate, String mtdPnl) {
        // 获取报告日期所在的年月
        LocalDateTime reportDateTime = reportDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        YearMonth reportYearMonth = YearMonth.from(reportDateTime);

        // 获取今年第一天
//        Year year = Year.from(reportDateTime);
//        LocalDateTime startOfYear = year.atDay(1).atStartOfDay();

        // 获取报告日期所在月份的第一天
        LocalDateTime startOfReportMonth = reportYearMonth.atDay(1).atStartOfDay();

        // 查询条件：今年开始到报告日期所在月份之前的数据
        LambdaQueryWrapper<PortfolioInformation> wrapper = new LambdaQueryWrapper<>();
        wrapper.lt(PortfolioInformation::getDate, startOfReportMonth)   // 小于报告日期所在月份第一天
                .orderByAsc(PortfolioInformation::getDate);

        List<PortfolioInformation> dataList = this.list(wrapper);

        // 获取每个月的最后一条数据
        List<PortfolioInformation> monthlyLastData = getLastOfMonthData(dataList);
        BigDecimal reduce = monthlyLastData.stream()
                .map(item -> {
                    String mtdReturn = item.getMTDReturn();
                    BigDecimal bigDecimal = parsePercentageString(mtdReturn);
                    return new BigDecimal(1).add(bigDecimal);
                }).reduce(new BigDecimal(1), BigDecimal::multiply);
        BigDecimal subtract = reduce.multiply(new BigDecimal(1).add(parsePercentageString(mtdPnl))).subtract(new BigDecimal(1));
        // 根据实际业务需求处理数据并返回结果
        // 示例：返回处理后的数据数量
        return subtract.multiply(new BigDecimal("100")).setScale(2, RoundingMode.HALF_UP)+"%";
    }
    public BigDecimal parsePercentageString(String percentageStr) {
        if (percentageStr == null || percentageStr.isEmpty()) {
            return BigDecimal.ZERO;
        }

        // 去除百分号和其他空格
        String cleanedStr = percentageStr.trim().replace("%", "");

        try {
            // 解析为 BigDecimal 并乘以 100
            BigDecimal value = new BigDecimal(cleanedStr);
            return value.divide(new BigDecimal("100"),4, RoundingMode.HALF_UP);
        } catch (NumberFormatException e) {
            // 如果解析失败，返回 0
            return BigDecimal.ZERO;
        }
    }
    @Override
    public String getYTDPnl(Date reportDate,String mtdPnl) {
        // 获取报告日期所在的年月
        LocalDateTime reportDateTime = reportDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        YearMonth reportYearMonth = YearMonth.from(reportDateTime);

        // 获取今年第一天
        Year year = Year.from(reportDateTime);
        LocalDateTime startOfYear = year.atDay(1).atStartOfDay();

        // 获取报告日期所在月份的第一天
        LocalDateTime startOfReportMonth = reportYearMonth.atDay(1).atStartOfDay();

        // 查询条件：今年开始到报告日期所在月份之前的数据
        LambdaQueryWrapper<PortfolioInformation> wrapper = new LambdaQueryWrapper<>();
        wrapper.ge(PortfolioInformation::getDate, startOfYear)           // 大于等于今年第一天
                .lt(PortfolioInformation::getDate, startOfReportMonth)   // 小于报告日期所在月份第一天
                .orderByAsc(PortfolioInformation::getDate);

        List<PortfolioInformation> dataList = this.list(wrapper);

            // 获取每个月的最后一条数据
            List<PortfolioInformation> monthlyLastData = getLastOfMonthData(dataList);
            BigDecimal reduce = monthlyLastData.stream()
                    .map(item -> {
                        String mtdReturn = item.getMTDReturn();
                        BigDecimal bigDecimal = parsePercentageString(mtdReturn);
                        return new BigDecimal(1).add(bigDecimal);
                    }).reduce(new BigDecimal(1), BigDecimal::multiply);
            BigDecimal subtract = reduce.multiply(new BigDecimal(1).add(parsePercentageString(mtdPnl))).subtract(new BigDecimal(1));
            // 根据实际业务需求处理数据并返回结果
            // 示例：返回处理后的数据数量
            return subtract.multiply(new BigDecimal("100")).setScale(2, RoundingMode.HALF_UP)+"%";
    }

    public static void main(String[] args) {
        ArrayList<Integer> integers = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
        ArrayList<Integer> integers1 = Lists.newArrayList(0);
        boolean b = integers.retainAll(integers1);
        System.out.println(integers);
    }


    @Override
    public PortfolioInformation getLastOfLastMonthInformation(YearMonth yearMonth) {
        LocalDateTime startOfMonth = yearMonth.minusMonths(1).atDay(1).atStartOfDay();
        LocalDateTime startOfNextMonth = yearMonth.atDay(1).atStartOfDay();

        LambdaQueryWrapper<PortfolioInformation> wrapper = new LambdaQueryWrapper<>();
        wrapper.ge(PortfolioInformation::getDate, startOfMonth)
                .lt(PortfolioInformation::getDate, startOfNextMonth)
                .orderByDesc(PortfolioInformation::getDate)
                .last("LIMIT 1");

        return this.getOne(wrapper);
    }

    @Override
    public PortfolioInformation getFirstInformation() {
        LambdaQueryWrapper<PortfolioInformation> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByAsc(PortfolioInformation::getDate)
                .last("LIMIT 1");
        return this.getOne( wrapper);
    }

    @Override
    public PortfolioInformation getFirstOfYearInformation(Year year) {
        LambdaQueryWrapper<PortfolioInformation> wrapper = new LambdaQueryWrapper<>();
        wrapper.ge(PortfolioInformation::getDate, year.atDay(1).atStartOfDay())
                .lt(PortfolioInformation::getDate, year.plusYears(1).atDay(1).atStartOfDay())
                .orderByAsc(PortfolioInformation::getDate)
                .last("LIMIT 1");
        return this.getOne( wrapper);
    }

    @Override
    public PortfolioInformation getFirstOfMonthInformation(YearMonth yearMonth) {
        LocalDateTime startOfMonth = yearMonth.atDay(1).atStartOfDay();
        LocalDateTime startOfNextMonth = yearMonth.plusMonths(1).atDay(1).atStartOfDay();

        LambdaQueryWrapper<PortfolioInformation> wrapper = new LambdaQueryWrapper<>();
        wrapper.ge(PortfolioInformation::getDate, startOfMonth)
                .lt(PortfolioInformation::getDate, startOfNextMonth)
                .orderByAsc(PortfolioInformation::getDate)
                .last("LIMIT 1");

        return this.getOne(wrapper);
    }

}
